/*
 * Niiuzu
 * Copyright (C) 2011  Thierry Nowak
 * 
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.niiuzu.client.screen.feed.group.factory;

import java.util.Arrays;
import java.util.Comparator;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.HasValue;
import com.google.inject.Inject;
import com.mvp4g.client.annotation.Presenter;
import com.mvp4g.client.presenter.LazyPresenter;
import com.niiuzu.client.eventbus.FeedEventBus;
import com.niiuzu.client.i18n.FeedChannelMessages;
import com.niiuzu.client.util.ClientContextFactory;
import com.niiuzu.client.util.LoadingTicket;
import com.niiuzu.client.util.SessionClient;
import com.niiuzu.client.util.callback.AbstractCallback;
import com.niiuzu.client.util.widget.HasSelectedValue;
import com.niiuzu.shared.model.FeedChannelGroup;
import com.niiuzu.shared.model.FeedStyle;
import com.niiuzu.shared.model.User;
import com.niiuzu.shared.rpc.FeedServiceAsync;

/**
 * Presenter dédié à la création de nouveaux thèmes.
 */
@Presenter(view = ChannelGroupFactoryViewImpl.class)
public class ChannelGroupFactoryPresenter extends
		LazyPresenter<ChannelGroupFactoryView, FeedEventBus> {

	@Inject
	private FeedServiceAsync feedService;

	private ClickHandler closeClickHandler;
	private ClickHandler validateClickHandler;

	private FeedChannelMessages feedChannelMessages = GWT
			.create(FeedChannelMessages.class);

	@Override
	public void bindView() {
		super.bindView();

		closeClickHandler = new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				view.hidePopup();
			}
		};
		view.getCloseButtonHasClickHandlers()
				.addClickHandler(closeClickHandler);
		view.getCancelHasClickHandlers().addClickHandler(closeClickHandler);

		validateClickHandler = new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				validateChannelGroup();
			}
		};
		view.getValidateHasClickHandlers()
				.addClickHandler(validateClickHandler);
	}

	/**
	 * Lance la validation du thème.
	 */
	protected void validateChannelGroup() {

		HasValue<String> nameField = view.getNameHasValue();
		HasSelectedValue<String> styleField = view.getStyleHasSelectedValue();

		String errorMessage = null;
		if (nameField.getValue().isEmpty()) {
			errorMessage = feedChannelMessages.errorChannelGroupNameMissing();
		} else if (styleField.getSelectedValue() == null) {
			errorMessage = feedChannelMessages.errorChannelGroupStyleMissing();
		}

		// Affichage d'une erreur
		if (errorMessage != null) {
			eventBus.businessErrorOccurred(errorMessage);
		}
		// Lancement de la création
		else {

			User user = SessionClient.getInstance().getUser();

			FeedStyle style = FeedStyle.valueOf(styleField.getSelectedValue());

			final LoadingTicket ticket = LoadingTicket.Factory
					.createTicket(getClass(), feedChannelMessages
							.loadingCreateChannelGroup());

			eventBus.loadingStarted(ticket);

			feedService.createChannelGroup(nameField.getValue(), style, user,
					ClientContextFactory.get(),
					new AbstractCallback<FeedChannelGroup>(eventBus, ticket) {
						@Override
						public void onSuccess(FeedChannelGroup result) {
							receiveCreatedChannelGroup(result, ticket);
						}
					});
		}
	}

	/**
	 * Réception d'une demande de création d'un nouveau thème.
	 * 
	 * @see FeedEventBus#newChannelGroupAsked()
	 */
	public void onNewChannelGroupAsked() {

		// RAZ de la vue
		view.getNameHasValue().setValue("");
		view.getStyleHasSelectedValue().clear();

		// Tri des styles possibles en fonction de leur libellé
		FeedStyle[] feedStyles = FeedStyle.values();
		Arrays.sort(feedStyles, new Comparator<FeedStyle>() {
			@Override
			public int compare(FeedStyle o1, FeedStyle o2) {
				String label1 = getStyleLabel(o1);
				String label2 = getStyleLabel(o2);

				return label1.compareTo(label2);
			}
		});

		// Remplissage de la liste des styles
		view.getStyleHasSelectedValue().addValue("", null);
		for (FeedStyle feedStyle : feedStyles) {
			String labelStyle = getStyleLabel(feedStyle);
			view.getStyleHasSelectedValue().addValue(labelStyle,
					feedStyle.toString());
		}

		view.showPopup();
	}

	/**
	 * Réception d'un nouveau thème.
	 * 
	 * @param nouvelle
	 *            instance de {@link FeedChannelGroup} à référencer.
	 * @param ticket
	 *            correspondant à l'appel asynchrone de la création du thème
	 */
	void receiveCreatedChannelGroup(FeedChannelGroup channelGroup,
			LoadingTicket ticket) {

		SessionClient.getInstance().addChannelGroup(channelGroup);

		view.hidePopup();
		eventBus.loadingFinished(ticket);

		eventBus.channelGroupCreated();
	}

	/**
	 * Comportement déclenché à la demande de fermeture de la popup.
	 */
	public ClickHandler getCloseClickHandler() {
		return closeClickHandler;
	}

	/**
	 * Comportement déclenché lors d'un clic sur le bouton "valider".
	 */
	public ClickHandler getValidateClickHandler() {
		return validateClickHandler;
	}

	/**
	 * Retourne le libellé correspondant au {@link FeedStyle}.
	 */
	String getStyleLabel(FeedStyle style) {
		String styleLabel = "";

		if (style != null) {
			switch (style) {
			case BLACK:
				styleLabel = feedChannelMessages.feedStyleBlack();
				break;
			case BLUE:
				styleLabel = feedChannelMessages.feedStyleBlue();
				break;
			case GREEN:
				styleLabel = feedChannelMessages.feedStyleGreen();
				break;
			case ORANGE:
				styleLabel = feedChannelMessages.feedStyleOrange();
				break;
			case PURPLE:
				styleLabel = feedChannelMessages.feedStylePurple();
				break;
			case RED:
				styleLabel = feedChannelMessages.feedStyleRed();
				break;
			case YELLOW:
				styleLabel = feedChannelMessages.feedStyleYellow();
				break;
			}
		}

		return styleLabel;
	}

	/* ********************************************************************** */
	/* ********************************************************************** */
	/* ********************************************************************** */

	/**
	 * JUnit - Définit un mock pour {@link FeedChannelMessages}.
	 */
	void setMockedFeedChannelMessages(FeedChannelMessages feedChannelMessages) {
		this.feedChannelMessages = feedChannelMessages;
	}

	/**
	 * JUnit - Définit un mock pour {@link FeedServiceAsync}.
	 */
	void setMockedFeedServiceAsync(FeedServiceAsync feedService) {
		this.feedService = feedService;
	}
}
